package se.jocke.nb.proxy.monitor.service.impl;

import io.netty.handler.codec.http.HttpRequest;
import java.util.concurrent.CopyOnWriteArraySet;
import org.littleshoot.proxy.HttpFilters;
import org.littleshoot.proxy.HttpFiltersSourceAdapter;
import org.littleshoot.proxy.HttpProxyServer;
import org.littleshoot.proxy.MitmManager;
import org.littleshoot.proxy.extras.SelfSignedMitmManager;
import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
import org.openide.util.lookup.ServiceProvider;
import se.jocke.nb.proxy.monitor.model.HttpMessage;
import se.jocke.nb.proxy.monitor.service.MessageListener;
import se.jocke.nb.proxy.monitor.service.HttpProxy;

@ServiceProvider(service = HttpProxy.class)
public class HttpProxyImpl implements HttpProxy {

    private HttpProxyServer proxyServer;

    private static final CopyOnWriteArraySet<MessageListener> LISTENERS = new CopyOnWriteArraySet<MessageListener>();

    public HttpProxyImpl() {
    }

    @Override
    public void start(int localPort, String targetHost, int targetPort) {
        proxyServer = DefaultHttpProxyServer.bootstrap()
                .withName("NB-Monitor")
                .withPort(localPort)
                .withListenOnAllAddresses(true)
                .withManInTheMiddle(new SelfSignedMitmManager())
                .withChainProxyManager(new ChainedProxyManagerImpl(targetHost, targetPort))
                .withFiltersSource(new HttpFiltersSourceAdapter() {
                    @Override
                    public HttpFilters filterRequest(HttpRequest originalRequest) {
                        return new HttpFiltersImpl(originalRequest, new MessageListener() {
                            @Override
                            public void onMessage(HttpMessage httpMessage) {
                                fireOnMessage(httpMessage);
                            }
                        });
                    }

                    @Override
                    public int getMaximumResponseBufferSizeInBytes() {
                        return 100000;
                    }

                    @Override
                    public int getMaximumRequestBufferSizeInBytes() {
                        return 100000;
                    }

                })
                .start();

    }

    @Override
    public void stop() {
        if (proxyServer != null) {
            proxyServer.stop();
        }
    }

    @Override
    public void registerListener(MessageListener listener) {
        LISTENERS.add(listener);
    }

    @Override
    public void removeListener(MessageListener listener) {
        LISTENERS.remove(listener);
    }

    public void fireOnMessage(HttpMessage httpMessage) {
        for (MessageListener messageListener : LISTENERS) {
            messageListener.onMessage(httpMessage);
        }
    }

}
